#ifndef __LOG_H__
#define __LOG_H__

#include "BlockQueue.h"
#include <iostream>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <stdarg.h>
#include "buffer.h"

class Log
{
public:
    void init(int level, const char *path = "./log",
              const char *suffix = ".log",
              int maxQueueCapacity = 1024);

    void flush();
    void write(int level,const char *format,...);

    static Log *Instance();
    static void FlushLogThread();

    int GetLevel();
    void SetLevel(int level);
    bool IsOpen() ;

private:
    Log();
    void AppendLogLevelTitle_(int level);
    virtual ~Log();
    void AsyncWrite();

private:
    static const int LOG_PATH_LEN = 256; // 日志文件路径最大长度
    static const int LOG_NAME_LEN = 256; // 日志文件名最大长度
    static const int MAX_LINES = 50000;  // 单个日志文件最大行数

    const char *path_;   // 日志文件路径
    const char *suffix_; // 日志文件后缀

    int MAX_LINES_; // 单个日志文件最大行数

    int lineCount_; // 当前日志文件行数
    int toDay_;     // 当前日期

    bool isOpen_; // 日志是否开启

    Buffer buff_;  // 日志缓冲区
    int level_;    // 日志级别
    bool isAsync_; // 是否异步写入

    FILE *fp_; // 文件指针
    std::unique_ptr<BlockQueue<std::string>> Que_;
    std::unique_ptr<std::thread> writeThread_;
    std::mutex Mtx_;
};


#define LOG_BASE(level, format, ...) \
    do {\
        Log* log = Log::Instance();\
        if (log->IsOpen() && log->GetLevel() <= level) {\
            log->write(level, format, ##__VA_ARGS__); \
            log->flush();\
        }\
    } while(0);

#define LOG_DEBUG(format, ...) do {LOG_BASE(0, format, ##__VA_ARGS__)} while(0);
#define LOG_INFO(format, ...) do {LOG_BASE(1, format, ##__VA_ARGS__)} while(0);
#define LOG_WARN(format, ...) do {LOG_BASE(2, format, ##__VA_ARGS__)} while(0);
#define LOG_ERROR(format, ...) do {LOG_BASE(3, format, ##__VA_ARGS__)} while(0);


#endif